package com.tarena.luban.worker.server.manange;
import com.tarena.luban.worker.server.bo.*;
import com.tarena.luban.worker.server.repository.WorkerAreaRepository;
import com.tarena.luban.worker.server.repository.WorkerCategoryRepsoitory;
import com.tarena.luban.worker.server.repository.WorkerRepository;
import com.tarena.passport.protocol.LoginUser;
import com.tarena.passport.sdk.context.SecurityContext;
import com.tarena.tp.attach.server.client.AttachApi;
import com.tarena.tp.attach.server.dto.AttachDTO;
import com.tarena.tp.attach.server.param.AttachUpdateParam;
import com.tarena.tp.attach.server.query.AttachQuery;
import com.tarena.tp.luban.worker.server.common.enums.AuditStatusEnum;
import com.tarena.tp.luban.worker.server.common.enums.ResultEnum;
import com.tarena.tp.luban.worker.server.dto.param.IdCardParam;
import com.tarena.tp.luban.worker.server.dto.param.WorkerAreaParam;
import com.tarena.tp.luban.worker.server.dto.param.WorkerCategoryParam;
import com.tarena.tp.luban.worker.server.dto.param.WorkerCreateParam;
import com.tedu.inn.commons.utils.Asserts;
import com.tedu.inn.protocol.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * @author java@tedu.cn
 * @version 1.0
 */
@Service
@Slf4j
public class WorkerServerService {
    @Autowired
    private WorkerRepository workerRepository;
    @Autowired
    private WorkerAreaRepository workerAreaRepository;
    @Autowired
    private WorkerCategoryRepsoitory workerCategoryRepsoitory;
    //domain不关心实现,没有实现,报错
    @Autowired
    private AttachApi attachApi;
    /**
     * 1. 补充userId
     * 2. 检查 手机号
     * 3. 检查 身份证 和真实名称是否匹配 TODO
     * 4. 存储 worker workerCategory workerArea
     * 使用定义好的repository接口
     * @param workerCreateParam
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Long create(WorkerCreateParam workerCreateParam) throws BusinessException {
        //获取userId
        Long userId=getUserIdByToken();
        //检查 手机号 身份证 UNDO
        checkPhoneAndIdCard(workerCreateParam);
        //挨个存储对应数据到持久层
        workerCreateParam.setUserId(userId);
        Long id=saveWorker(workerCreateParam);
        saveWorkerArea(workerCreateParam);
        saveWorkerCategory(workerCreateParam);
        return id;
    }

    /**
     * 先删除,后新增
     * @param workerCreateParam
     */
    private void saveWorkerCategory(WorkerCreateParam workerCreateParam) {
        workerCategoryRepsoitory.deleteByUserId(workerCreateParam.getUserId());
        List<WorkerCategoryParam> workerCategoryParams = workerCreateParam.getWorkerCategoryParams();
        if (!CollectionUtils.isEmpty(workerCreateParam.getWorkerCategoryParams())){
            //循环
            workerCategoryParams.forEach(param -> {
                param.setUserId(workerCreateParam.getUserId());
                workerCategoryRepsoitory.save(param);
            });
        }
    }

    /**
     * 先删除,后新增
     * @param workerCreateParam
     */
    private void saveWorkerArea(WorkerCreateParam workerCreateParam) {
        workerAreaRepository.deleteByUserId(workerCreateParam.getUserId());
        //循环存储 <foreach>
        //TODO 批量存
        List<WorkerAreaParam> workerAreaParams
                = workerCreateParam.getWorkerAreaParams();
        for (WorkerAreaParam workerAreaParam : workerAreaParams) {
            //提交的参数 workerCategoryParam中和workerParam类似的,也没有userId;
            workerAreaParam.setUserId(workerCreateParam.getUserId());
            //insert into worker_area
            workerAreaRepository.save(workerAreaParam);
        }
    }

    /**
     * 1. 当前用户有可能已经是师傅了.
     * 1.1 先查讯数据库是否有当前用户.师傅信息 有就报错 没有 就新增
     * 1.2 不管有没有 如果有就删除.重新新增
     * @param workerCreateParam
     * @return
     */
    private Long saveWorker(WorkerCreateParam workerCreateParam) throws BusinessException {
        //如果当前用户在数据库中有师傅信息,就删除 重新入住师傅信息
        workerRepository.delete(workerCreateParam.getUserId());
        Long id=workerRepository.save(workerCreateParam);
        //rpc 调用 将身份信息,worker-id,和当前图片传递给attach系统,做更新
        //远程调用
        try{
            //远程调用,更新已经上传的图片,绑定到当前worker
            createAttach(id,workerCreateParam.getAttachList());
        }catch (Exception e){
            //远程调用失败
            throw new BusinessException(ResultEnum.ATTACH_FAILED);
        }
        return id;
    }
    //人为定义的类型.
    private static final Integer bizType=100;
    private void createAttach(Long businessId, List<IdCardParam> attachList) {
        //要将attachList 图片(attach服务 没有绑定业务)
        //封装远程调用参数 attach执行一个简单update attach set bysiness_id=#{参数} business_id=#{师傅id}
        //where id=#{当前图片id}
        List<AttachUpdateParam> attachUpdateParams=new ArrayList<>();
        //封装
        for (IdCardParam idCardParam : attachList) {
            //参数元素
            AttachUpdateParam attachUpdateParam=new AttachUpdateParam();
            attachUpdateParam.setIsCover(idCardParam.getType());
            // 图片id bizId bizType 主要数据
            attachUpdateParam.setId(idCardParam.getId());
            attachUpdateParam.setBusinessType(bizType);
            attachUpdateParam.setBusinessId(businessId.intValue());
            //添加到list
            attachUpdateParams.add(attachUpdateParam);
        }
        //调用远程
        attachApi.batchUpdateAttachByIdList(attachUpdateParams);
    }

    private void checkPhoneAndIdCard(WorkerCreateParam workerCreateParam) {
        //UNDO
        log.info("check phone and idCard,now passed");
    }

    private Long getUserIdByToken() throws BusinessException {
        LoginUser loginToken = SecurityContext.getLoginToken();
        //判断 user登录还是没登录 如果loginUser是空的,说明没登录
        Asserts.isTrue(loginToken==null,
                new BusinessException(ResultEnum.USER_TOKEN_VERIFY_FAILED));
        return loginToken.getUserId();
    }

    /**
     * 1. 从security上下文中拿到userId
     * 2. 查询worker 利用userId查询 workerBO(非空判断)
     * 3. 查询区域 查询服务种类 查询附件 查询账户(TODO)
     * 4. 审核通过没通过,没通过,添加一个拒绝原因(TODO)
     * @return
     */
    public WorkerBO getWorkerDetail() throws BusinessException {
        Long userId = getUserIdByToken();
        //查询worker
        WorkerBO workerBO=workerRepository.getWorker(userId);
        if (workerBO!=null){
            //服务区域
            List<WorkerAreaBO> workerAreas=getWorkerArea(userId);
            //workerBO set一下
            workerBO.setWorkerAreaBOList(workerAreas);
            //服务分类
            List<WorkerCategoryBO> workerCategories=getWorkerCategory(userId);
            workerBO.setWorkerCategoryBOList(workerCategories);
            //查询账户 TODO
            AccountBO accountBO=new AccountBO();
            workerBO.setAccountBO(accountBO);
            //查询附件
            List<AttachInfoBO> attaches=getWorkerAttach(bizType,workerBO.getId());
            workerBO.setAttachInfoBOList(attaches);
            //审核信息 TODO 目前没审核 状态是2 告知前端展示状态 未入住是3
            //workerBO.setAuditStatus(AuditStatusEnum.UNAUDITED.getValue());
            return workerBO;
        }else {
            //登录之初,还没入住,worker是null
            return null;
        }
    }

    private List<AttachInfoBO> getWorkerAttach(Integer bizType, Long bizId) throws BusinessException {
        //封装query查询参数,远程调用,调用完了
        //attachApi.getAttachInfoByParam();
        //转化 自己手动转化
        try{
            //封装对应参数query
            AttachQuery attachQuery=new AttachQuery();
            attachQuery.setBusinessId(bizId.intValue());
            attachQuery.setBusinessType(bizType);
            //远程调用获取结果
            List<AttachDTO> attachInfoDTOS = attachApi.getAttachInfoByParam(attachQuery);
            //结果解析和转化对象
            List<AttachInfoBO> attaches=new ArrayList<>();
            if (!CollectionUtils.isEmpty(attachInfoDTOS)){
                attachInfoDTOS.forEach(attach ->{
                    //当前windows url http://localhost:8092/static/+ DTO.fileUUID
                    AttachInfoBO attachInfoBO=new AttachInfoBO();
                    attachInfoBO.setUrl("http://localhost:8092/static/"+attach.getFileUuid());
                    //返回结果 add 当前封装好的bo对象
                    attaches.add(attachInfoBO);
                });
            }
            return attaches;
        }catch (Exception e){
            throw new BusinessException(ResultEnum.ATTACH_FAILED);
        }
    }

    private List<WorkerCategoryBO> getWorkerCategory(Long userId) {
        return workerCategoryRepsoitory.selectByUserId(userId);
    }

    private List<WorkerAreaBO> getWorkerArea(Long userId) {
        return workerAreaRepository.selectByUserId(userId);
    }
}
